package org.convallaria.system.biz.listener;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.convallaria.system.biz.service.SecurityAuditService;
import org.convallaria.system.biz.service.TokenBlacklistService;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

/**
 * 安全事件监听器
 * 监听系统安全相关事件并记录审计日志
 * 
 * @author convallaria
 * @since 1.0.0
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class SecurityEventListener {

    private final SecurityAuditService securityAuditService;
    private final TokenBlacklistService tokenBlacklistService;

    /**
     * 监听登录成功事件
     */
    @EventListener
    public void handleLoginSuccessEvent(LoginSuccessEvent event) {
        try {
            securityAuditService.recordLoginEvent(
                event.getUserId(),
                event.getUsername(),
                event.getIp(),
                true,
                null
            );
            log.info("记录登录成功事件: 用户={}, IP={}", event.getUsername(), event.getIp());
        } catch (Exception e) {
            log.error("记录登录成功事件失败", e);
        }
    }

    /**
     * 监听登录失败事件
     */
    @EventListener
    public void handleLoginFailureEvent(LoginFailureEvent event) {
        try {
            securityAuditService.recordLoginEvent(
                event.getUserId(),
                event.getUsername(),
                event.getIp(),
                false,
                event.getReason()
            );
            log.warn("记录登录失败事件: 用户={}, IP={}, 原因={}", event.getUsername(), event.getIp(), event.getReason());
        } catch (Exception e) {
            log.error("记录登录失败事件失败", e);
        }
    }

    /**
     * 监听密码修改事件
     */
    @EventListener
    public void handlePasswordChangeEvent(PasswordChangeEvent event) {
        try {
            securityAuditService.recordPasswordChangeEvent(
                event.getUserId(),
                event.getOperatorId(),
                event.isSuccess(),
                event.getReason()
            );
            log.info("记录密码修改事件: 用户={}, 操作人={}, 成功={}", 
                event.getUserId(), event.getOperatorId(), event.isSuccess());
        } catch (Exception e) {
            log.error("记录密码修改事件失败", e);
        }
    }

    /**
     * 监听Token撤销事件
     */
    @EventListener
    public void handleTokenRevokeEvent(TokenRevokeEvent event) {
        try {
            tokenBlacklistService.addToBlacklist(
                event.getToken(),
                event.getReason()
            );
            log.info("记录Token撤销事件: Token={}, 原因={}", event.getToken(), event.getReason());
        } catch (Exception e) {
            log.error("记录Token撤销事件失败", e);
        }
    }

    /**
     * 登录成功事件
     */
    public static class LoginSuccessEvent {
        private final Long userId;
        private final String username;
        private final String ip;
        private final LocalDateTime eventTime;

        public LoginSuccessEvent(Long userId, String username, String ip) {
            this.userId = userId;
            this.username = username;
            this.ip = ip;
            this.eventTime = LocalDateTime.now();
        }

        public Long getUserId() { return userId; }
        public String getUsername() { return username; }
        public String getIp() { return ip; }
        public LocalDateTime getEventTime() { return eventTime; }
    }

    /**
     * 登录失败事件
     */
    public static class LoginFailureEvent {
        private final Long userId;
        private final String username;
        private final String ip;
        private final String reason;
        private final LocalDateTime eventTime;

        public LoginFailureEvent(Long userId, String username, String ip, String reason) {
            this.userId = userId;
            this.username = username;
            this.ip = ip;
            this.reason = reason;
            this.eventTime = LocalDateTime.now();
        }

        public Long getUserId() { return userId; }
        public String getUsername() { return username; }
        public String getIp() { return ip; }
        public String getReason() { return reason; }
        public LocalDateTime getEventTime() { return eventTime; }
    }

    /**
     * 密码修改事件
     */
    public static class PasswordChangeEvent {
        private final Long userId;
        private final Long operatorId;
        private final boolean success;
        private final String reason;
        private final LocalDateTime eventTime;

        public PasswordChangeEvent(Long userId, Long operatorId, boolean success, String reason) {
            this.userId = userId;
            this.operatorId = operatorId;
            this.success = success;
            this.reason = reason;
            this.eventTime = LocalDateTime.now();
        }

        public Long getUserId() { return userId; }
        public Long getOperatorId() { return operatorId; }
        public boolean isSuccess() { return success; }
        public String getReason() { return reason; }
        public LocalDateTime getEventTime() { return eventTime; }
    }

    /**
     * Token撤销事件
     */
    public static class TokenRevokeEvent {
        private final String token;
        private final String reason;
        private final LocalDateTime eventTime;

        public TokenRevokeEvent(String token, String reason) {
            this.token = token;
            this.reason = reason;
            this.eventTime = LocalDateTime.now();
        }

        public String getToken() { return token; }
        public String getReason() { return reason; }
        public LocalDateTime getEventTime() { return eventTime; }
    }
}
